/*
 * ArbolB.cpp
 *
 *  Created on: 08/11/2011
 *      Author: agustin
 */

#include "ArbolB.h"

ArbolB::ArbolB() {
	Lista<NodoB*>* lista_temp = new Lista<NodoB*>;
	Lista<NodoB*>* lista_temp2 = new Lista<NodoB*>;
	NodoB* nodo_temp = new NodoB();

	IteradorIndice itInd;

	Configuracion* conf = Configuracion::getConf(PATH_CONF);

	itInd.setPaso(conf->front_coding());
//	itInd.setPaso(1);

	while (itInd.tieneSiguiente()) {
		reg_arbolB* regB = new reg_arbolB;
		regB->posicion = itInd.getPosicion();
		super_reg* reg = itInd.proximoRegistro();
		regB->termino = reg->termino;

		if (nodo_temp->addDato(regB) == -1) {
			//El nodo esta lleno, se agrega a la lista
			lista_temp->agregar(nodo_temp);
			nodo_temp = new NodoB();
			nodo_temp->addDato(regB);
		}
		this->deleteSuperReg(reg);
	}

//agrego el nodo final
	lista_temp->agregar(nodo_temp);

	NodoB* padre = new NodoB();
	int pos_hijo = 0;

	bool salir = false;
	IteradorLista<NodoB*> itLista = lista_temp->iterador();
	while (!salir) {
		nodo_temp = itLista.siguiente();
		reg_arbolB* regB = nodo_temp->getExtra();
		if (regB != NULL && itLista.tieneSiguiente()) {
			if (padre->addDato(regB) == -1) {
				//El nodo esta lleno, se agrega a la lista
				lista_temp2->agregar(padre);
				padre = new NodoB();
				padre->addDato(regB);
				pos_hijo = 0;
			}
			padre->setHijo(nodo_temp, pos_hijo);
			pos_hijo++;
		} else { //RegB es NULL, es el final de la lista

			//cout << "Lista 2 tam:" << lista_temp2->size() << endl;

			if (padre->tieneExtra()) {
				//Subo un nivel el ultimo nodo porque no puede ser asignado como hijo
				lista_temp2->agregar(padre);
				lista_temp2->agregar(nodo_temp);
        if (!itLista.tieneSiguiente()){
        	 //Continua un nivel mas arriba
					padre = new NodoB();
					pos_hijo = 0;
					//cambio a la lista de padres
					delete lista_temp;
					lista_temp = lista_temp2;
					lista_temp2 = new Lista<NodoB*>;
					itLista = lista_temp->iterador();
        }
			} else {
				padre->setHijo(nodo_temp, pos_hijo);
				if (lista_temp2->estaVacia()) {
					this->root = padre;
					salir = true;
					//root->print();
				} else {
					lista_temp2->agregar(padre);
					//Continua un nivel mas arriba
					padre = new NodoB();
					pos_hijo = 0;
					//cambio a la lista de padres
					delete lista_temp;
					lista_temp = lista_temp2;
					lista_temp2 = new Lista<NodoB*>;
					itLista = lista_temp->iterador();
				}
			}
		}
	}

	delete lista_temp;
	delete lista_temp2;
	//cout << "Server Ready" << endl;
}

void ArbolB::print() {
	root->print();
}

void ArbolB::deleteSuperReg(super_reg* reg) {
//no se por que me explota el valgrind si pongo esto
//	IteradorLista<reg_docs_variable*> itReg = reg->lista->iterador();
//	while (itReg.tieneSiguiente()) {
//		delete itReg.siguiente();
//	}

	delete reg->lista;
	delete reg;
}

super_reg* ArbolB::buscar(string termino) {
	int pos = root->buscar(termino);
	if (pos == -1) {
		return NULL;
	}

//Me ubico en el Bloque de front coding y lo itero hasta encontrar la palabra
	IteradorIndice itInd;

	super_reg* reg = NULL;
	reg = itInd.buscar(termino, pos, 1);

	return reg;

	/*
	 IteradorIndice itInd;
	 itInd.setPaso(1);
	 itInd.setPosicion(pos);

	 Configuracion* conf = Configuracion::getConf(PATH_CONF);

	 super_reg* reg = NULL;
	 for (int i = 0; i < conf->front_coding(); i++) {
	 if (itInd.tieneSiguiente()) {
	 reg = itInd.proximoRegistro();
	 if (reg->termino == termino) {
	 return reg;
	 }
	 deleteSuperReg(reg);
	 }
	 }
	 */
	return NULL;
}

ArbolB::~ArbolB() {
	delete this->root;
}

